<template>
  <div class="file-upload-container">
    <div v-if="mode === 'DESIGN'">
      <el-button size="small" icon="el-icon-paperclip" round>选择文件</el-button>
      <ellipsis-view :row="1" :content="placeholder + sizeTip" hoverTip slot="tip" class="el-upload__tip" />
    </div>
    <div v-else style="width: 100%">
      <el-upload
        v-if="!$attrs.disabled && _value.length < maxNumber"
        ref="upload"
        action=""
        :file-list="_value"
        :show-file-list="false"
        :accept="fileTypes.join(',')"
        :multiple="maxNumber > 1"
        :limit="maxNumber"
        :before-upload="beforeUpload"
        :on-exceed="oneExceed"
        :http-request="customUpload"
        :on-error="onError"
      >
        <template v-if="$attrs.drag">
          <el-icon><Upload /></el-icon>
          <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        </template>
        <el-button v-else type="primary" :icon="Paperclip" size="small" round>选择文件</el-button>
        <ellipsis-view :row="1" :content="placeholder + sizeTip" hoverTip slot="tip" class="el-upload__tip" />
      </el-upload>
      <div class="file-list">
        <div class="file-list__item" v-for="(item, index) in _value" :key="item.fileId">
          <div class="file-list__item-container">
            <div class="file-list__item-name one-ellipsis" @click="handelDownload(item)">{{ item.fileName || item.name }}</div>
            <div v-if="!$attrs.disabled" class="file-list__item-del" @click="handleRemove(index)">x</div>
          </div>
          <el-progress
            v-if="multipartOssStore.loadingArr[item.fileId] !== 100"
            :show-text="false"
            :percentage="multipartOssStore.loadingArr[item.fileId]"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed, getCurrentInstance, useAttrs } from "vue";
import { Upload, Paperclip } from "@element-plus/icons-vue";
import { isEmpty } from "lodash";
import { fileReadRole, setACL, signatureUrl, isExistObject } from "@/utils/aliOssUpload";
import { getCurrentTime, getRandom } from "@/utils/crm";
import useMultipartOssStore from "@/store/modules/multipartOss";
import defaultConfig from "@/settings";

const { proxy } = getCurrentInstance();
const $attrs = useAttrs();
const props = defineProps({
  modelValue: {
    type: Array,
    default: () => []
  },
  mode: {
    type: String,
    default: "DESIGN"
  },
  required: {
    type: Boolean,
    default: false
  },
  readonly: {
    type: Boolean,
    default: false
  },
  maxSize: {
    type: Number,
    default: 5
  },
  maxNumber: {
    type: Number,
    default: 20
  },

  placeholder: {
    type: String,
    default: "请选择附件"
  },
  fileTypes: {
    type: Array,
    default: () => {
      return [];
    }
  }
});
const emit = defineEmits(["update:modelValue"]);
const multipartOssStore = useMultipartOssStore();

const sizeTip = computed(() => {
  if (props.fileTypes.length > 0) {
    return ` | 只允许上传[${String(props.fileTypes).replaceAll(",", "、")}]格式的文件，且单个附件不超过${props.maxSize}MB`;
  }
  return props.maxSize > 0 ? ` | 单个附件不超过${props.maxSize}MB` : "";
});
const _value = computed({
  get() {
    if (props.modelValue?.length) {
      props.modelValue.forEach(item => {
        multipartOssStore.loadingArr[item.fileId] = 100;
      });
    }
    return Array.isArray(props.modelValue) ? props.modelValue : [];
  },
  set(val) {
    emit("update:modelValue", val);
  }
});

const beforeUpload = file => {
  if (props.maxSize <= 0) {
    proxy.$modal.msgError(`请设置正确的文件大小！`);
    return false;
  }
  const maxSize = file.size / 1024 / 1024 < props.maxSize;
  if (!maxSize) {
    proxy.$modal.msgError(`单个文件大小不能超过${props.maxSize}M!`);
    return false;
  }
  return true;
};
const oneExceed = () => {
  proxy.$modal.msgError(`最多上传${props.maxNumber}个文件`);
  return false;
};
const getSuffix = fileName => {
  return fileName.slice(fileName.lastIndexOf(".") + 1);
};
const getFileName = fileName => {
  return fileName.slice(0, fileName.lastIndexOf("."));
};
const fileToBlob = file => {
  return {
    fileId: file.uid,
    uid: file.uid,
    name: file.name,
    size: file.size,
    type: file.type,
    suffix: file.suffix,
    fileUrl: URL.createObjectURL(file)
  };
};
const customUpload = async option => {
  let file = option.file;
  let objName = `${defaultConfig.fileFolder}/${file.name}`;
  const fileId = file.uid;
  _value.value.push(fileToBlob(option.file));
  multipartOssStore.loadingArr[fileId] = 0;
  if (await isExistObject(objName)) {
    let fileName = `${getFileName(option.file.name)}-${getCurrentTime()}${getRandom()}.${getSuffix(file.name)}`;
    file = new File([file], fileName, { type: file.type });
    objName = `${defaultConfig.fileFolder}/${fileName}`;
    console.log("文件名重复>>>添加时间戳、4位随机数", objName);
  }
  multipartOssStore
    .submit(objName, file, fileId)
    .then(async res => {
      await setACL(objName, fileReadRole.publicRead);
      const fileUrl = await signatureUrl(objName);
      multipartOssStore.completeState[option.file.uid] = true;
      const fileObj = {
        fileUrl: fileUrl ? `${fileUrl}`.split("?")[0] : "",
        fileId,
        fileName: file.name
      };
      _value.value.some((item, index) => {
        if (item.fileId === fileObj.fileId) {
          _value.value[index] = { ...fileObj };
          return true;
        }
      });
      emit("update:modelValue", _value.value);
    })
    .catch(err => {
      console.log(err);
      alert(`文件上传错误：${JSON.stringify(err)}`);
    });
};
const handelDownload = item => {
  window.open(item.fileUrl);
};
const handleRemove = index => {
  _value.value.splice(index, 1);
};
const onError = err => {
  alert(`onError:${JSON.stringify(err)}`);
  console.log("onError>>>", err);
};

if (isEmpty(_value.value) && !$attrs.disabled) {
  _value.value = $attrs.defaultValue;
}
</script>

<style lang="less" scoped>
@text-color-regular: #606266;
.file-upload-container {
  width: 100%;
}
.one-ellipsis {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.file-list {
  width: 100%;
  margin: 10px auto;

  &__item {
    cursor: pointer;
    margin-bottom: 5px;
    font-size: 14px;

    &-container {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 1px;
    }

    &-name {
      width: 95%;
      color: @text-color-regular;
    }

    &-del {
      display: inline-flex;
      display: -webkit-inline-flex;
      justify-content: center;
      align-items: center;
      width: 20px;
      height: 20px;
      border-radius: 50%;

      &:hover {
        background-color: rgba(0, 0, 0, 0.2);
      }
    }
  }
}
</style>
